home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1843 / 1843.xpi / content / firebug / sourceFile.js < prev    next >
Text File  |  2010-01-15  |  20KB  |  646 lines

  1. /* See license.txt for terms of usage */
  2.  
  3. FBL.ns(function() { with (FBL)
  4. {
  5.     const Cc = Components.classes;
  6.     const Ci = Components.interfaces;
  7.  
  8.     const PCMAP_SOURCETEXT = Ci.jsdIScript.PCMAP_SOURCETEXT;
  9.     const PCMAP_PRETTYPRINT = Ci.jsdIScript.PCMAP_PRETTYPRINT;
  10.  
  11.  
  12. //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  13. /*
  14.  * SourceFile one for every compilation unit.
  15.  * Unique URL for each. (href)
  16.  * Unique outerScript, the statements outside of any function defintion
  17.  * sourceCache keyed by href has source for this compilation unit
  18.  * Stored by href in context.
  19.  * Contains array of jsdIScript for functions (scripts) defined in this unit
  20.  * May contain line table (for sources viewed)
  21.  */
  22.  
  23. Firebug.SourceFile = function (compilation_unit_type)
  24. {
  25.     this.compilation_unit_type = compilation_unit_type; /*@explore*/
  26. }
  27.  
  28. Firebug.SourceFile.prototype =
  29. {
  30.     getBaseLineOffset: function()
  31.     {
  32.         return 0;
  33.     },
  34.  
  35.     toString: function()
  36.     {
  37.         var str = (this.compilation_unit_type?this.compilation_unit_type+" ":"")+this.href+" script.tags( ";
  38.         if (this.outerScript)
  39.             str += (this.outerScript.isValid?this.outerScript.tag:"X") +"| ";
  40.         if (this.innerScripts)
  41.         {
  42.             var numberInvalid = 0;
  43.             for (var p in this.innerScripts)
  44.             {
  45.                 var script = this.innerScripts[p];
  46.                 if (script.isValid)
  47.                     str += p+" ";
  48.                 else
  49.                     numberInvalid++;
  50.             }
  51.         }
  52.         str += ")"+(numberInvalid ? "("+numberInvalid+" invalid)" : "");
  53.         return str;
  54.     },
  55.  
  56.     forEachScript: function(callback)
  57.      {
  58.          if (this.outerScript)
  59.              callback(this.outerScript);
  60.          if (this.innerScripts)
  61.          {
  62.              for (var p in this.innerScripts)
  63.              {
  64.                  var script = this.innerScripts[p];
  65.                  var rc = callback(script);
  66.                  if (rc)
  67.                      return rc;
  68.              }
  69.          }
  70.      },
  71.  
  72.      getLineRanges: function()
  73.      {
  74.          var str = "";
  75.          this.forEachScript(function appendARange(script)
  76.          {
  77.              var endLineNumber = script.baseLineNumber + script.lineExtent;
  78.              str += " "+script.baseLineNumber +"-("+script.tag+")-"+endLineNumber;
  79.          });
  80.          return str;
  81.      },
  82.  
  83.      getSourceLength: function()
  84.      {
  85.              return this.sourceLength;
  86.      },
  87.  
  88.      getLine: function(context, lineNo)
  89.      {
  90.          return context.sourceCache.getLine(this.href, lineNo);
  91.      },
  92.  
  93.      addToLineTable: function(script)
  94.      {
  95.          if (!script || !script.isValid)
  96.          {
  97.              return;
  98.          }
  99.  
  100.          // For outer scripts, a better algorithm would loop over PC, use pcToLine to mark the lines.
  101.          // This assumes there are fewer PCs in an outer script than lines, probably true for large systems.
  102.          // And now addToLineTable is only used for outerScripts (eval and top-level).
  103.          // But since we can't know the range of PC values we cannot use that approach.
  104.  
  105.          if (!this.outerScriptLineMap)
  106.              this.outerScriptLineMap = [];
  107.  
  108.          var lineCount = script.lineExtent + 1;
  109.          var offset = this.getBaseLineOffset();
  110.          if (lineCount > 100)
  111.              lineCount = 100; // isLineExecutable requires about 1ms per line, so it can only be called for toy programs
  112.  
  113.          for (var i = 0; i <= lineCount; i++)
  114.          {
  115.              var scriptLineNo = i + script.baseLineNumber;  // the max is (i + script.baseLineNumber + script.lineExtent)
  116.              var mapLineNo = scriptLineNo - offset;
  117.              try
  118.              {
  119.                  if (script.isLineExecutable(scriptLineNo, this.pcmap_type))
  120.                      this.outerScriptLineMap.push(mapLineNo);
  121.              }
  122.              catch (e)
  123.              {
  124.                  // I guess not...
  125.              }
  126.  
  127.          }
  128.      },
  129.  
  130.      addToLineTableByPCLoop: function(script)
  131.      {
  132.          // This code is not called; it crashes FF3pre https://bugzilla.mozilla.org/show_bug.cgi?id=430205
  133.          if (!this.outerScriptLineMap)
  134.              this.outerScriptLineMap = {};
  135.  
  136.          var lineCount = script.lineExtent;
  137.          var offset = this.getBaseLineOffset();
  138.          for (var i = 0; i <= 10*lineCount; i++)
  139.          {
  140.              var lineFromPC = script.pcToLine(i, this.pcmap_type);
  141.              //FBTrace.sysout("lib.SourceFile.addToLineTableByPCLoop pc="+i+" line: "+lineFromPC+"\n");
  142.              this.outerScriptLineMap[lineFromPC] = script;
  143.              if (lineFromPC >= lineCount) break;
  144.          }
  145.  
  146.      },
  147.  
  148.      getScriptsAtLineNumber: function(lineNo, mustBeExecutableLine)
  149.      {
  150.          var offset = this.getBaseLineOffset();
  151.  
  152.          if (!this.innerScripts)
  153.              return; // eg URLOnly
  154.  
  155.          var targetLineNo = lineNo + offset;  // lineNo is user-viewed number, targetLineNo is jsd number
  156.  
  157.          var scripts = [];
  158.          for (var p in this.innerScripts)
  159.          {
  160.              var script = this.innerScripts[p];
  161.              if (mustBeExecutableLine && !script.isValid) continue;
  162.              this.addScriptAtLineNumber(scripts, script, targetLineNo, mustBeExecutableLine, offset);
  163.          }
  164.  
  165.          if (this.outerScript && !(mustBeExecutableLine && !this.outerScript.isValid) )
  166.              this.addScriptAtLineNumber(scripts, this.outerScript, targetLineNo, mustBeExecutableLine, offset);
  167.  
  168.          return (scripts.length > 0) ? scripts : false;
  169.      },
  170.  
  171.      addScriptAtLineNumber: function(scripts, script, targetLineNo, mustBeExecutableLine, offset)
  172.      {
  173.          // script.isValid will be true.
  174.          if (targetLineNo >= script.baseLineNumber)
  175.          {
  176.              if ( (script.baseLineNumber + script.lineExtent) >= targetLineNo)
  177.              {
  178.                  if (mustBeExecutableLine)
  179.                  {
  180.                      try
  181.                      {
  182.                          if (!script.isLineExecutable(targetLineNo, this.pcmap_type) )
  183.                          {
  184.                              return;
  185.                          }
  186.                      }
  187.                      catch (e)
  188.                      {
  189.                          // Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [jsdIScript.isLineExecutable]
  190.                          return;
  191.                      }
  192.                  }
  193.                  scripts.push(script);
  194.              }
  195.          }
  196.      },
  197.  
  198.      scriptsIfLineCouldBeExecutable: function(lineNo)  // script may not be valid
  199.      {
  200.          var scripts = this.getScriptsAtLineNumber(lineNo, true);
  201.          if (!scripts && this.outerScriptLineMap && (this.outerScriptLineMap.indexOf(lineNo) != -1) )
  202.              return [this.outerScript];
  203.          return scripts;
  204.      },
  205.  
  206.      hasScript: function(script)
  207.      {
  208.          if (this.outerScript && (this.outerScript.tag == script.tag) )
  209.              return true;
  210.          // XXXjjb Don't use indexOf or similar tests that rely on ===, since we are really working with
  211.          // wrappers around jsdIScript, not script themselves.  I guess.
  212.  
  213.         return ( this.innerScripts && this.innerScripts.hasOwnProperty(script.tag) );
  214.      },
  215.  
  216.      // these objects map JSD's values to correct values
  217.      getScriptAnalyzer: function(script)
  218.      {
  219.          if (this.outerScript && (script.tag == this.outerScript.tag) )
  220.              return this.getOuterScriptAnalyzer();
  221.          return new Firebug.SourceFile.NestedScriptAnalyzer(this);
  222.      },
  223.  
  224.      // return.path: group/category label, return.name: item label
  225.      getObjectDescription: function()
  226.      {
  227.          return FBL.splitURLBase(this.href);
  228.      },
  229.  
  230.      isEval: function()
  231.      {
  232.          return (this.compilation_unit_type == "eval-level") || (this.compilation_unit_type == "newFunction");
  233.      },
  234.  
  235.      isEvent: function()
  236.      {
  237.          return (this.compilation_unit_type == "event");
  238.      },
  239.  
  240.      loadScriptLines: function(context)  // array of lines
  241.      {
  242.          if (this.source)
  243.              return this.source;
  244.          else
  245.              return context.sourceCache.load(this.href);
  246.      },
  247.  
  248.      getOuterScriptAnalyzer: function()
  249.      {
  250.          FBTrace.sysout("getOuterScriptAnalyzer not overridden for "+sourceFile, this);
  251.      },
  252.  
  253. }
  254.  
  255. Firebug.SourceFile.summarizeSourceLineArray = function(sourceLines, size)
  256. {
  257.     var buf  = "";
  258.     for (var i = 0; i < sourceLines.length; i++)
  259.      {
  260.          var aLine = sourceLines[i].substr(0,240);  // avoid huge lines
  261.          buf += aLine.replace(/\s/, " ", "g");
  262.          if (buf.length > size || aLine.length > 240)
  263.              break;
  264.      }
  265.      return buf.substr(0, size);
  266. };
  267.  
  268.  
  269. Firebug.SourceFile.NestedScriptAnalyzer = function(sourceFile)
  270. {
  271.     this.sourceFile = sourceFile;
  272. }
  273.  
  274. Firebug.SourceFile.NestedScriptAnalyzer.prototype =
  275. {
  276.     // Adjust JSD line numbers based on origin of script
  277.     getSourceLineFromFrame: function(context, frame)
  278.     {
  279.         return frame.line - (this.sourceFile.getBaseLineOffset());
  280.     },
  281.     // Interpret frame to give fn(args)
  282.     getFunctionDescription: function(script, context, frame)
  283.     {
  284.         if (frame)
  285.         {
  286.             var name = frame.name;
  287.             var args = FBL.getFunctionArgValues(frame);
  288.         }
  289.         else
  290.         {
  291.             var name = script.functionName;
  292.             var args = [];
  293.         }
  294.  
  295.         if (name ==  "anonymous")
  296.         {
  297.             name = FBL.guessFunctionName(this.sourceFile.href, this.getBaseLineNumberByScript(script), context);
  298.         }
  299.  
  300.         return {name: name, args: args};
  301.     },
  302.  
  303.     // link to source for this script.
  304.     getSourceLinkForScript: function (script)
  305.     {
  306.         var line = this.getBaseLineNumberByScript(script);
  307.         return new FBL.SourceLink(this.sourceFile.href, line, "js");
  308.     },
  309.  
  310.     getBaseLineNumberByScript: function(script)
  311.     {
  312.         return script.baseLineNumber - (this.sourceFile.getBaseLineOffset() - 1);
  313.     }
  314. }
  315.  
  316. Firebug.SourceFile.addScriptsToSourceFile = function(sourceFile, outerScript, innerScripts)
  317. {
  318.     // Attach the innerScripts for use later
  319.     if (!sourceFile.innerScripts)
  320.          sourceFile.innerScripts = {};
  321.  
  322.      var total = 0;
  323.      while (innerScripts.hasMoreElements())
  324.      {
  325.          var script = innerScripts.getNext();
  326.          if (!script || ( (script instanceof Ci.jsdIScript) && !script.tag) )
  327.          {
  328.              continue;
  329.          }
  330.          sourceFile.innerScripts[script.tag] = script;
  331.      }
  332. }
  333.  
  334. //------------
  335. Firebug.EvalLevelSourceFile = function(url, script, eval_expr, source, mapType, innerScriptEnumerator) // ctor
  336. {
  337.     this.href = url.href;
  338.     this.hrefKind = url.kind;
  339.      this.outerScript = script;
  340.      this.containingURL = script.fileName;
  341.      this.evalExpression = eval_expr;
  342.      this.sourceLength = source.length;
  343.      this.source = source;
  344.      this.pcmap_type = mapType;
  345.      Firebug.SourceFile.addScriptsToSourceFile(this, script, innerScriptEnumerator);
  346. };
  347.  
  348. Firebug.EvalLevelSourceFile.prototype =
  349.     descend(new Firebug.SourceFile("eval-level"), // shared prototype
  350. {
  351.     getLine: function(context, lineNo)
  352.     {
  353.         return this.source[lineNo - 1];
  354.     },
  355.  
  356.     getBaseLineOffset: function()
  357.     {
  358.         return this.outerScript.baseLineNumber - 1; // baseLineNumber always valid even after jsdIscript isValid false
  359.     },
  360.  
  361.     getObjectDescription: function()
  362.     {
  363.          if (this.hrefKind == "source" || this.hrefKind == "data")
  364.              return FBL.splitURLBase(this.href);
  365.  
  366.          if (!this.summary)
  367.          {
  368.              if (this.evalExpression)
  369.                  this.summary = Firebug.SourceFile.summarizeSourceLineArray(this.evalExpression.substr(0, 240), 120);
  370.              if (!this.summary)
  371.                  this.summary = "";
  372.              if (this.summary.length < 120)
  373.                  this.summary = "eval("+this.summary + "...)=" + Firebug.SourceFile.summarizeSourceLineArray(this.source, 120 - this.summary.length);
  374.          }
  375.          var containingFileDescription = FBL.splitURLBase(this.containingURL);
  376.          return {path: containingFileDescription.path, name: containingFileDescription.name+"/eval: "+this.summary };
  377.     },
  378.  
  379.     getOuterScriptAnalyzer: function()
  380.     {
  381.         return new Firebug.EvalLevelSourceFile.OuterScriptAnalyzer(this);
  382.     },
  383.  
  384. });
  385.  
  386. Firebug.EvalLevelSourceFile.OuterScriptAnalyzer = function(sourceFile)
  387. {
  388.     this.sourceFile = sourceFile;
  389. }
  390.  
  391. Firebug.EvalLevelSourceFile.OuterScriptAnalyzer.prototype =
  392. {
  393.     // Adjust JSD line numbers based on origin of script
  394.     getSourceLineFromFrame: function(context, frame)
  395.     {
  396.         return frame.line - this.sourceFile.getBaseLineOffset();
  397.     },
  398.     // Interpret frame to give fn(args)
  399.     getFunctionDescription: function(script, context, frame)
  400.     {
  401.         return {name: "eval", args: [this.evalExpression] };
  402.     },
  403.     getSourceLinkForScript: function (script)
  404.     {
  405.         return new FBL.SourceLink(this.sourceFile.href, 1, "js");
  406.     }
  407. }
  408.  
  409. //------------
  410. Firebug.EventSourceFile = function(url, script, title, source, innerScriptEnumerator)
  411. {
  412.      this.href = url;
  413.      this.outerScript = script;
  414.      this.containingURL = script.fileName;
  415.      this.title = title;
  416.      this.sourceLines = source; // points to the sourceCache lines
  417.      this.sourceLength = source.length;
  418.      this.pcmap_type = PCMAP_PRETTYPRINT;
  419.  
  420.      Firebug.SourceFile.addScriptsToSourceFile(this, script, innerScriptEnumerator);
  421. };
  422.  
  423. Firebug.EventSourceFile.prototype =    descend(new Firebug.SourceFile("event"),  // prototypical inheritance
  424. {
  425.     getLine: function(context, lineNo)
  426.     {
  427.         return this.sourceLines[lineNo - 1];
  428.     },
  429.  
  430.     getBaseLineOffset: function()
  431.     {
  432.         return 1;
  433.     },
  434.  
  435.     getObjectDescription: function()
  436.     {
  437.         if (!this.summary)
  438.              this.summary = Firebug.SourceFile.summarizeSourceLineArray(this.sourceLines, 120);
  439.  
  440.         var containingFileDescription = FBL.splitURLBase(this.containingURL);
  441.  
  442.         return {path: containingFileDescription.path, name: containingFileDescription.name+"/event: "+this.summary };
  443.     },
  444.  
  445.     getOuterScriptAnalyzer: function()
  446.     {
  447.         return new Firebug.EventSourceFile.OuterScriptAnalyzer(this);
  448.     },
  449.  
  450. });
  451.  
  452. Firebug.EventSourceFile.OuterScriptAnalyzer = function(sourceFile)
  453. {
  454.     this.sourceFile = sourceFile;
  455. }
  456.  
  457. Firebug.EventSourceFile.OuterScriptAnalyzer.prototype =
  458. {
  459.     // Adjust JSD line numbers based on origin of script
  460.     getSourceLineFromFrame: function(context, frame)
  461.     {
  462.         var script = frame.script;
  463.         var line = script.pcToLine(frame.pc, PCMAP_PRETTYPRINT);
  464.         return line - 1;
  465.     },
  466.     // Interpret frame to give fn(args)
  467.     getFunctionDescription: function(script, context, frame)
  468.     {
  469.         var fn = unwrapIValue(script.functionObject);  //?? should be name of?
  470.         if (frame)
  471.             var args = FBL.getFunctionArgValues(frame);
  472.         else
  473.             var args = [];
  474.         return {name: fn, args: args};
  475.     },
  476.     getSourceLinkForScript: function (script)
  477.     {
  478.         return new FBL.SourceLink(this.sourceFile.href, 1, "js");  // XXXjjb why do we need FBL.??
  479.     }
  480. }
  481.  
  482. //------------
  483. Firebug.SourceFile.CommonBase =
  484. {
  485.     getSourceLength: function()
  486.     {
  487.         if (!this.sourceLength)
  488.             this.sourceLength = this.context.sourceCache.load(this.href).length;
  489.         return this.sourceLength;
  490.     },
  491.  
  492.     getOuterScriptAnalyzer: function()
  493.     {
  494.         return Firebug.TopLevelSourceFile.OuterScriptAnalyzer;
  495.     },
  496.  
  497. }
  498. //-----------
  499. Firebug.TopLevelSourceFile = function(url, outerScript, sourceLength, innerScriptEnumerator)
  500. {
  501.     this.href = url;
  502.     this.outerScript = outerScript;  // Beware may not be valid after we return!!
  503.     this.sourceLength = sourceLength;
  504.     this.pcmap_type = PCMAP_SOURCETEXT;
  505.  
  506.     Firebug.SourceFile.addScriptsToSourceFile(this, outerScript, innerScriptEnumerator);
  507. }
  508.  
  509. Firebug.TopLevelSourceFile.prototype = descend(new Firebug.SourceFile("top-level"), Firebug.SourceFile.CommonBase);
  510.  
  511.  
  512. Firebug.TopLevelSourceFile.OuterScriptAnalyzer = {
  513.     // Adjust JSD line numbers based on origin of script
  514.     getSourceLineFromFrame: function(context, frame)
  515.     {
  516.         return frame.line;
  517.     },
  518.     // Interpret frame to give fn(args)
  519.     getFunctionDescription: function(script, context, frame)
  520.     {
  521.         var file_name = FBL.getFileName(FBL.normalizeURL(script.fileName)); // this is more useful that just "top_level"
  522.         file_name = file_name ? file_name: "__top_level__";
  523.         return {name: file_name, args: []};
  524.     },
  525.     getSourceLinkForScript: function (script)
  526.     {
  527.         return FBL.SourceLink(FBL.normalizeURL(script.fileName), script.baseLineNumber, "js")
  528.     }
  529. }
  530.  
  531. //-------
  532.  
  533. Firebug.EnumeratedSourceFile = function(url) // we don't have the outer script and we delay source load.
  534. {
  535.     this.href = new String(url);  // may not be outerScript file name, eg this could be an enumerated eval
  536.     this.innerScripts = {};
  537.     this.pcmap_type = PCMAP_SOURCETEXT;
  538. }
  539.  
  540. Firebug.EnumeratedSourceFile.prototype = descend(
  541.         new Firebug.SourceFile("enumerated"),
  542.         Firebug.SourceFile.CommonBase);
  543.  
  544. //---------
  545. Firebug.NoScriptSourceFile = function(context, url) // Somehow we got the URL, but not the script
  546. {
  547.     this.href = url;  // we know this much
  548.     this.innerScripts = {};
  549. }
  550.  
  551. Firebug.NoScriptSourceFile.prototype = descend(
  552.         new Firebug.SourceFile("URLOnly"),
  553.         Firebug.SourceFile.CommonBase);
  554.  
  555. //---------// javascript in a .xul or .xml file, no outerScript
  556. Firebug.XULSourceFile = function(url, innerScriptEnumerator)
  557. {
  558.     this.href = url;
  559.     this.pcmap_type = PCMAP_SOURCETEXT;
  560.  
  561.     Firebug.SourceFile.addScriptsToSourceFile(this, null, innerScriptEnumerator);
  562. }
  563.  
  564. Firebug.XULSourceFile.prototype = descend(
  565.         new Firebug.SourceFile("xul"),
  566.         Firebug.SourceFile.CommonBase);
  567.  
  568. //---------
  569. Firebug.ScriptTagSourceFile = function(context, url, scriptTagNumber) // we don't have the outer script and we delay source load
  570. {
  571.     this.context = context;
  572.     this.href = url;  // we know this is not an eval
  573.     this.scriptTagNumber = scriptTagNumber;
  574.     this.innerScripts = {};
  575.     this.pcmap_type = PCMAP_SOURCETEXT;
  576. }
  577.  
  578. Firebug.ScriptTagSourceFile.prototype = descend(
  579.         new Firebug.SourceFile("scriptTag"),
  580.         Firebug.SourceFile.CommonBase);
  581.  
  582. //-------------------
  583. Firebug.SourceFile.getSourceFileByScript = function(context, script)
  584. {
  585.     if (!context.sourceFileMap)
  586.          return null;
  587.  
  588.     // Other algorithms are possible:
  589.     //   We could store an index, context.sourceFileByTag
  590.     //   Or we could build a tree keyed by url, with SpiderMonkey script.fileNames at the top and our urls below
  591.     var lucky = context.sourceFileMap[script.fileName];  // we won't be lucky for file:/ urls, no normalizeURL applied
  592.     if (lucky && lucky.hasScript(script))
  593.         return lucky;
  594.  
  595.     for (var url in context.sourceFileMap)
  596.     {
  597.         var sourceFile = context.sourceFileMap[url];
  598.         if (sourceFile.hasScript(script))
  599.             return sourceFile;
  600.     }
  601. };
  602.  
  603. Firebug.SourceFile.getScriptAnalyzer = function(context, script)
  604. {
  605.     var sourceFile = Firebug.SourceFile.getSourceFileByScript(context, script);
  606.      if (sourceFile)
  607.      {
  608.          var analyzer = sourceFile.getScriptAnalyzer(script);
  609.          return analyzer;
  610.      }
  611.      return undefined;
  612. };
  613.  
  614. Firebug.SourceFile.getSourceFileAndLineByScript= function(context, script, frame)
  615. {
  616.     var sourceFile = Firebug.SourceFile.getSourceFileByScript(context, script);
  617.     if (sourceFile)
  618.     {
  619.         var analyzer = sourceFile.getScriptAnalyzer(script);
  620.         if (analyzer)
  621.             var line = frame ? analyzer.getSourceLineFromFrame(context, frame) : analyzer.getBaseLineNumberByScript(script);
  622.         else
  623.             var line = 0;
  624.  
  625.         return { sourceFile: sourceFile, lineNo: line };
  626.     }
  627. };
  628.  
  629. Firebug.SourceFile.guessEnclosingFunctionName = function(url, line, context)
  630. {
  631.     var sourceFile = context.sourceFileMap[url];
  632.     if (sourceFile)
  633.     {
  634.         var scripts = sourceFile.getScriptsAtLineNumber(line);
  635.         if (scripts)
  636.         {
  637.             var script = scripts[0]; // TODO try others?
  638.             var analyzer = sourceFile.getScriptAnalyzer(script);
  639.             line = analyzer.getBaseLineNumberByScript(script);
  640.         }
  641.     }
  642.     return FBL.guessFunctionName(url, line-1, context);
  643. };
  644.  
  645. }});
  646.